/**
 * 清理工作器
 * EndoSight-UC 医疗AI系统
 *
 * 处理后台维护任务、数据清理和系统优化
 * 支持HIPAA数据保留策略和合规清理
 */

import queueManager from '../config/queueConfig.js';
import structuredLogger from '../utils/structuredLogger.js';
import auditService from '../services/auditService.js';
import { QueueType, QueuePriority } from '../config/queueConfig.js';
import db from '../config/database.js';
import fs from 'fs';
import path from 'path';
import winston from 'winston';
import os from 'os';

// 配置日志记录器
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console({
      format: winston.format.simple()
    }),
    new winston.transports.File({
      filename: 'logs/cleanup-worker.log',
      level: 'info'
    })
  ]
});

/**
 * 清理工作器主类
 */
class CleanupWorker {
  constructor() {
    this.isRunning = false;
    this.cleanupTasks = new Map();
    this.scheduledTasks = [];
    this.startTime = null;
    this.queue = null;

    // 清理配置
    this.cleanupConfig = {
      // 数据保留策略（天）
      auditLogs: 2555,      // 7年 - HIPAA要求
      userSessions: 30,     // 30天
      failedTasks: 7,       // 7天
      completedTasks: 30,   // 30天
      tempFiles: 1,         // 1天
      errorLogs: 90,        // 90天
      metrics: 365,         // 1年
      // 文件大小限制（MB）
      maxLogFileSize: 100,
      maxTempFileSize: 500
    };
  }

  /**
   * 启动清理工作器
   */
  async start() {
    try {
      logger.info('正在启动清理工作器...', {
        cleanupConfig: this.cleanupConfig,
        nodeVersion: process.version,
        platform: os.platform()
      });

      // 获取清理队列
      this.queue = queueManager.getQueue(QueueType.CLEANUP);
      if (!this.queue) {
        logger.warn('清理队列未初始化，检查Redis连接状态');
        if (!queueManager.redisAvailable) {
          logger.warn('Redis不可用，清理工作器将以降级模式运行');
          this.isRunning = true;
          this.startTime = Date.now();
          return;
        }
        throw new Error('清理队列未初始化');
      }

      // 设置队列处理器
      this.setupQueueProcessor();

      // 注册定期清理任务
      this.setupScheduledCleanup();

      this.isRunning = true;
      this.startTime = Date.now();

      logger.info('✅ 清理工作器启动成功', {
        pid: process.pid,
        scheduledTasks: this.scheduledTasks.length
      });

      // 设置优雅关闭
      this.setupGracefulShutdown();

      return true;
    } catch (error) {
      logger.error('清理工作器启动失败:', error);
      throw error;
    }
  }

  /**
   * 设置队列处理器
   */
  setupQueueProcessor() {
    // 清理过期审计日志
    this.queue.process('cleanup-audit-logs', 1, async (job) => {
      return await this.cleanupAuditLogs(job);
    });

    // 清理过期用户会话
    this.queue.process('cleanup-user-sessions', 1, async (job) => {
      return await this.cleanupUserSessions(job);
    });

    // 清理过期任务记录
    this.queue.process('cleanup-expired-tasks', 1, async (job) => {
      return await this.cleanupExpiredTasks(job);
    });

    // 清理临时文件
    this.queue.process('cleanup-temp-files', 1, async (job) => {
      return await this.cleanupTempFiles(job);
    });

    // 清理错误日志
    this.queue.process('cleanup-error-logs', 1, async (job) => {
      return await this.cleanupErrorLogs(job);
    });

    // 清理过期的Prometheus指标
    this.queue.process('cleanup-metrics', 1, async (job) => {
      return await this.cleanupMetrics(job);
    });

    // 数据库优化
    this.queue.process('database-optimization', 1, async (job) => {
      return await this.performDatabaseOptimization(job);
    });

    // 合规检查
    this.queue.process('compliance-check', 1, async (job) => {
      return await this.performComplianceCheck(job);
    });

    // 队列事件监听
    this.queue.on('completed', (job, result) => {
      this.logCleanupCompletion(job, result);
    });

    this.queue.on('failed', (job, error) => {
      this.logCleanupFailure(job, error);
    });
  }

  /**
   * 设置定期清理任务
   */
  setupScheduledCleanup() {
    // 每天凌晨2点执行全面清理
    const scheduleDailyCleanup = () => {
      const now = new Date();
      const nextRun = new Date(now);
      nextRun.setHours(2, 0, 0, 0);

      if (nextRun <= now) {
        nextRun.setDate(nextRun.getDate() + 1);
      }

      const delay = nextRun.getTime() - now.getTime();

      setTimeout(() => {
        this.addJob('comprehensive-cleanup', {
          cleanupType: 'daily',
          timestamp: new Date().toISOString()
        }, {
          priority: QueuePriority.LOW,
          delay: 0
        });

        scheduleDailyCleanup(); // 重新调度
      }, delay);

      logger.info('已调度每日清理任务', {
        nextRun: nextRun.toISOString(),
        delay: delay / 1000 / 60 + ' minutes'
      });
    };

    // 每小时清理临时文件
    const scheduleHourlyTempCleanup = () => {
      setTimeout(() => {
        this.addJob('cleanup-temp-files', {
          cleanupType: 'hourly',
          timestamp: new Date().toISOString()
        }, {
          priority: QueuePriority.LOW
        });

        scheduleHourlyTempCleanup();
      }, 60 * 60 * 1000); // 1小时
    };

    // 每15分钟清理失败任务
    const scheduleFrequentCleanup = () => {
      setTimeout(() => {
        this.addJob('cleanup-failed-tasks', {
          cleanupType: 'frequent',
          timestamp: new Date().toISOString()
        }, {
          priority: QueuePriority.LOW
        });

        scheduleFrequentCleanup();
      }, 15 * 60 * 1000); // 15分钟
    };

    // 启动所有调度任务
    scheduleDailyCleanup();
    scheduleHourlyTempCleanup();
    scheduleFrequentCleanup();

    this.scheduledTasks = [
      'daily-cleanup',
      'hourly-temp-cleanup',
      'frequent-cleanup'
    ];

    logger.info('定期清理任务已设置', {
      tasks: this.scheduledTasks
    });
  }

  /**
   * 清理过期审计日志
   */
  async cleanupAuditLogs(job) {
    const { data } = job;
    const startTime = Date.now();

    try {
      logger.info('开始清理过期审计日志', {
        jobId: job.id,
        retentionDays: this.cleanupConfig.auditLogs
      });

      const cutoffDate = new Date();
      cutoffDate.setDate(cutoffDate.getDate() - this.cleanupConfig.auditLogs);

      // 清理主审计日志表
      const deletedAuditLogs = await db.execute(`
        DELETE FROM audit_logs
        WHERE created_at < ? AND id NOT IN (
          SELECT audit_log_id FROM compliance_violations
          WHERE remediation_status IN ('pending', 'in_progress')
        )
      `, [cutoffDate.toISOString()]);

      // 清理医疗数据访问日志
      const deletedMedicalAccessLogs = await db.execute(`
        DELETE FROM medical_data_access_logs
        WHERE created_at < ?
      `, [cutoffDate.toISOString()]);

      // 清理AI推理审计记录
      const deletedAIInferenceAudit = await db.execute(`
        DELETE FROM ai_inference_audit
        WHERE created_at < ?
      `, [cutoffDate.toISOString()]);

      // 清理文件操作审计
      const deletedFileOperationAudit = await db.execute(`
        DELETE FROM file_operation_audit
        WHERE created_at < ?
      `, [cutoffDate.toISOString()]);

      // 清理数据导出审计
      const deletedDataExportAudit = await db.execute(`
        DELETE FROM data_export_audit
        WHERE created_at < ?
      `, [cutoffDate.toISOString()]);

      const duration = Date.now() - startTime;
      const totalDeleted = deletedAuditLogs + deletedMedicalAccessLogs +
                          deletedAIInferenceAudit + deletedFileOperationAudit +
                          deletedDataExportAudit;

      logger.info('审计日志清理完成', {
        deletedAuditLogs,
        deletedMedicalAccessLogs,
        deletedAIInferenceAudit,
        deletedFileOperationAudit,
        deletedDataExportAudit,
        totalDeleted,
        duration
      });

      // 记录清理审计日志
      await structuredLogger.audit('AUDIT_LOGS_CLEANUP', 'system', null, {
        cleanupType: 'audit_logs',
        recordsDeleted: totalDeleted,
        cutoffDate: cutoffDate.toISOString(),
        duration,
        performedBy: 'cleanup_worker'
      });

      return {
        success: true,
        cleanupType: 'audit_logs',
        recordsDeleted: totalDeleted,
        duration,
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      logger.error('清理审计日志失败:', error);
      throw error;
    }
  }

  /**
   * 清理过期用户会话
   */
  async cleanupUserSessions(job) {
    const { data } = job;
    const startTime = Date.now();

    try {
      logger.info('开始清理过期用户会话', {
        jobId: job.id,
        retentionDays: this.cleanupConfig.userSessions
      });

      const cutoffDate = new Date();
      cutoffDate.setDate(cutoffDate.getDate() - this.cleanupConfig.userSessions);

      const deletedSessions = await db.execute(`
        DELETE FROM user_sessions
        WHERE (session_status = 'expired' OR session_status = 'terminated')
        AND logout_time < ?
      `, [cutoffDate.toISOString()]);

      const duration = Date.now() - startTime;

      logger.info('用户会话清理完成', {
        deletedSessions,
        duration
      });

      return {
        success: true,
        cleanupType: 'user_sessions',
        recordsDeleted: deletedSessions,
        duration,
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      logger.error('清理用户会话失败:', error);
      throw error;
    }
  }

  /**
   * 清理过期任务记录
   */
  async cleanupExpiredTasks(job) {
    const { data } = job;
    const startTime = Date.now();

    try {
      logger.info('开始清理过期任务记录', {
        jobId: job.id,
        cleanupType: data.cleanupType
      });

      let deletedTasks = 0;
      const cutoffDate = new Date();

      if (data.cleanupType === 'frequent') {
        // 清理失败任务（7天）
        cutoffDate.setDate(cutoffDate.getDate() - this.cleanupConfig.failedTasks);
        deletedTasks = await db.execute(`
          DELETE FROM scoring_tasks
          WHERE status = 'failed' AND created_at < ?
        `, [cutoffDate.toISOString()]);
      } else {
        // 清理完成的任务（30天）
        cutoffDate.setDate(cutoffDate.getDate() - this.cleanupConfig.completedTasks);
        deletedTasks = await db.execute(`
          DELETE FROM scoring_tasks
          WHERE status = 'completed' AND created_at < ?
        `, [cutoffDate.toISOString()]);
      }

      const duration = Date.now() - startTime;

      logger.info('任务记录清理完成', {
        deletedTasks,
        cleanupType: data.cleanupType,
        duration
      });

      return {
        success: true,
        cleanupType: 'expired_tasks',
        recordsDeleted: deletedTasks,
        duration,
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      logger.error('清理过期任务失败:', error);
      throw error;
    }
  }

  /**
   * 清理临时文件
   */
  async cleanupTempFiles(job) {
    const { data } = job;
    const startTime = Date.now();

    try {
      logger.info('开始清理临时文件', {
        jobId: job.id,
        cleanupType: data.cleanupType
      });

      const tempDirs = [
        './uploads/temp',
        './uploads/chunks',
        './logs/temp'
      ];

      let deletedFiles = 0;
      let deletedSize = 0;

      for (const dir of tempDirs) {
        if (fs.existsSync(dir)) {
          const files = fs.readdirSync(dir);

          for (const file of files) {
            const filePath = path.join(dir, file);
            const stats = fs.statSync(filePath);

            // 检查文件是否超过保留期限
            const cutoffTime = Date.now() - (this.cleanupConfig.tempFiles * 24 * 60 * 60 * 1000);

            if (stats.mtime.getTime() < cutoffTime) {
              try {
                const fileSize = stats.size;
                fs.unlinkSync(filePath);
                deletedFiles++;
                deletedSize += fileSize;

                // 检查是否超过大小限制
                if (fileSize > this.cleanupConfig.maxTempFileSize * 1024 * 1024) {
                  logger.warn('删除超大临时文件', {
                    file,
                    size: fileSize,
                    maxSize: this.cleanupConfig.maxTempFileSize * 1024 * 1024
                  });
                }

              } catch (error) {
                logger.error('删除临时文件失败', {
                  file,
                  error: error.message
                });
              }
            }
          }
        }
      }

      const duration = Date.now() - startTime;

      logger.info('临时文件清理完成', {
        deletedFiles,
        deletedSize: (deletedSize / 1024 / 1024).toFixed(2) + ' MB',
        duration
      });

      return {
        success: true,
        cleanupType: 'temp_files',
        recordsDeleted: deletedFiles,
        spaceFreed: deletedSize,
        duration,
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      logger.error('清理临时文件失败:', error);
      throw error;
    }
  }

  /**
   * 清理错误日志
   */
  async cleanupErrorLogs(job) {
    const { data } = job;
    const startTime = Date.now();

    try {
      logger.info('开始清理错误日志', {
        jobId: job.id,
        retentionDays: this.cleanupConfig.errorLogs
      });

      const logDir = './logs';
      const cutoffTime = Date.now() - (this.cleanupConfig.errorLogs * 24 * 60 * 60 * 1000);
      let deletedFiles = 0;
      let deletedSize = 0;

      if (fs.existsSync(logDir)) {
        const files = fs.readdirSync(logDir);

        for (const file of files) {
          if (file.endsWith('.log')) {
            const filePath = path.join(logDir, file);
            const stats = fs.statSync(filePath);

            if (stats.mtime.getTime() < cutoffTime) {
              try {
                const fileSize = stats.size;
                fs.unlinkSync(filePath);
                deletedFiles++;
                deletedSize += fileSize;

                // 检查是否超过大小限制
                if (fileSize > this.cleanupConfig.maxLogFileSize * 1024 * 1024) {
                  logger.warn('删除超大日志文件', {
                    file,
                    size: fileSize
                  });
                }

              } catch (error) {
                logger.error('删除日志文件失败', {
                  file,
                  error: error.message
                });
              }
            }
          }
        }
      }

      const duration = Date.now() - startTime;

      logger.info('错误日志清理完成', {
        deletedFiles,
        deletedSize: (deletedSize / 1024 / 1024).toFixed(2) + ' MB',
        duration
      });

      return {
        success: true,
        cleanupType: 'error_logs',
        recordsDeleted: deletedFiles,
        spaceFreed: deletedSize,
        duration,
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      logger.error('清理错误日志失败:', error);
      throw error;
    }
  }

  /**
   * 清理过期的Prometheus指标
   */
  async cleanupMetrics(job) {
    const { data } = job;
    const startTime = Date.now();

    try {
      logger.info('开始清理过期的Prometheus指标', {
        jobId: job.id,
        retentionDays: this.cleanupConfig.metrics
      });

      // 这里可以添加Prometheus指标清理逻辑
      // 例如：清理时序数据库中的旧数据

      const duration = Date.now() - startTime;

      logger.info('Prometheus指标清理完成', {
        duration
      });

      return {
        success: true,
        cleanupType: 'metrics',
        duration,
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      logger.error('清理Prometheus指标失败:', error);
      throw error;
    }
  }

  /**
   * 执行数据库优化
   */
  async performDatabaseOptimization(job) {
    const { data } = job;
    const startTime = Date.now();

    try {
      logger.info('开始执行数据库优化', {
        jobId: job.id
      });

      // SQLite数据库优化
      const optimizations = [];

      // 清理碎片
      await db.execute('VACUUM');
      optimizations.push('VACUUM');

      // 重建索引
      await db.execute('REINDEX');
      optimizations.push('REINDEX');

      // 分析统计信息
      await db.execute('ANALYZE');
      optimizations.push('ANALYZE');

      const duration = Date.now() - startTime;

      logger.info('数据库优化完成', {
        optimizations,
        duration
      });

      return {
        success: true,
        cleanupType: 'database_optimization',
        optimizations,
        duration,
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      logger.error('数据库优化失败:', error);
      throw error;
    }
  }

  /**
   * 执行合规检查
   */
  async performComplianceCheck(job) {
    const { data } = job;
    const startTime = Date.now();

    try {
      logger.info('开始执行合规检查', {
        jobId: job.id
      });

      const complianceIssues = [];

      // 检查数据保留政策
      const auditRetention = await db.execute(`
        SELECT COUNT(*) as count
        FROM audit_logs
        WHERE created_at < date('now', '-7 years')
      `);

      if (auditRetention > 0) {
        complianceIssues.push({
          type: 'data_retention',
          severity: 'warning',
          description: `发现${auditRetention}条超过7年保留期的审计日志`,
          recommendation: '执行数据清理以符合HIPAA要求'
        });
      }

      // 检查未解决的合规违规
      const openViolations = await db.execute(`
        SELECT COUNT(*) as count
        FROM compliance_violations
        WHERE remediation_status IN ('pending', 'in_progress')
      `);

      if (openViolations > 0) {
        complianceIssues.push({
          type: 'open_violations',
          severity: 'high',
          description: `发现${openViolations}个未解决的合规违规`,
          recommendation: '立即处理所有合规违规'
        });
      }

      // 检查PHI数据处理
      const phiWithoutConsent = await db.execute(`
        SELECT COUNT(*) as count
        FROM medical_data_access_logs
        WHERE consent_verified = 0 AND created_at > date('now', '-30 days')
      `);

      if (phiWithoutConsent > 0) {
        complianceIssues.push({
          type: 'phi_consent',
          severity: 'critical',
          description: `发现${phiWithoutConsent}条未经同意验证的PHI访问`,
          recommendation: '审查最近的PHI访问记录'
        });
      }

      const duration = Date.now() - startTime;

      logger.info('合规检查完成', {
        issuesFound: complianceIssues.length,
        duration
      });

      return {
        success: true,
        cleanupType: 'compliance_check',
        complianceIssues,
        issuesFound: complianceIssues.length,
        duration,
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      logger.error('合规检查失败:', error);
      throw error;
    }
  }

  /**
   * 添加清理任务
   */
  async addJob(type, data, options = {}) {
    try {
      const jobData = {
        ...data,
        type,
        id: crypto.randomUUID(),
        timestamp: new Date().toISOString(),
        cleanupConfig: this.cleanupConfig
      };

      const jobOptions = {
        ...options,
        priority: options.priority || QueuePriority.LOW,
        attempts: 1,
        removeOnComplete: 10,
        removeOnFail: 5
      };

      const job = await this.queue.add(type, jobData, jobOptions);

      logger.info('清理任务已添加', {
        jobId: job.id,
        type,
        priority: jobOptions.priority
      });

      return job;

    } catch (error) {
      logger.error('添加清理任务失败:', error);
      throw error;
    }
  }

  /**
   * 记录清理完成日志
   */
  logCleanupCompletion(job, result) {
    logger.info('清理任务完成', {
      jobId: job.id,
      type: result.cleanupType,
      recordsDeleted: result.recordsDeleted || 0,
      duration: result.duration
    });
  }

  /**
   * 记录清理失败日志
   */
  logCleanupFailure(job, error) {
    logger.error('清理任务失败', {
      jobId: job.id,
      type: job.data.type,
      error: error.message,
      attempts: job.attemptsMade
    });
  }

  /**
   * 设置优雅关闭
   */
  setupGracefulShutdown() {
    const shutdown = async (signal) => {
      logger.info(`收到${signal}信号，正在优雅关闭清理工作器...`);

      this.isRunning = false;

      try {
        if (this.queue) {
          await this.queue.pause();
        }

        logger.info('等待当前清理任务完成...');
        await new Promise(resolve => setTimeout(resolve, 30000)); // 30秒超时

        logger.info('✅ 清理工作器已优雅关闭', {
          uptime: this.startTime ? Date.now() - this.startTime : 0
        });

        process.exit(0);

      } catch (error) {
        logger.error('优雅关闭过程中发生错误:', error);
        process.exit(1);
      }
    };

    process.on('SIGTERM', () => shutdown('SIGTERM'));
    process.on('SIGINT', () => shutdown('SIGINT'));
    process.on('SIGUSR2', () => shutdown('SIGUSR2'));
  }

  /**
   * 获取工作器状态
   */
  getStatus() {
    return {
      isRunning: this.isRunning,
      cleanupTasks: this.cleanupTasks.size,
      scheduledTasks: this.scheduledTasks.length,
      cleanupConfig: this.cleanupConfig,
      uptime: this.startTime ? Date.now() - this.startTime : 0,
      queueStatus: this.queue ? 'active' : 'inactive'
    };
  }
}

// 创建并导出工作器实例
const cleanupWorker = new CleanupWorker();

export default cleanupWorker;